package net.homeip.mmhg.game;


import java.util.LinkedList;
import java.util.List;

import net.homeip.mmhg.domain.Task;

import org.joda.time.DateTime;

/**
 * Full info about task.
 *
 * @author ilya gerasimov
 */
public class ObtainedTask {
	
	private static int MAX_ATTEMPTS = 20;
	
	private Task task;
	private DateTime start;
	private DateTime firstHint;
	private DateTime secondHint;
	private DateTime finished;
	private int attempts = 0;
	private List<String> answers;
	private int guessedCodes = 0;
	
	public enum TaskState { OBTAINED,
							FIRST_HINT, 
							SECOND_HINT, 
							FINISHED }
	
	public enum TaskResult { UNKNOWN, 
							 GUESSED, 
							 FIRST_HINT_GUESSED, 
							 SECOND_HINT_GUESSED, 
							 TIMEOUT, 
							 REJECTED, 
							 STOPPED }
	
	private TaskState state;
	private TaskResult result;
	
	public ObtainedTask(Task task) {
		this.task = task;
		start = new DateTime();
		state = TaskState.OBTAINED;
		result = TaskResult.UNKNOWN;
		answers = new LinkedList<String>(task.getAnswers());
	}
	
	public Task getTask() {
		return task;
	}
	public void setTask(Task task) {
		this.task = task;
	}
	public DateTime getStart() {
		return start;
	}
	public void setStart(DateTime start) {
		this.start = start;
	}
	public DateTime getFirstHint() {
		return firstHint;
	}
	public void setFirstHint(DateTime firstHint) {
		this.firstHint = firstHint;
	}
	public DateTime getSecondHint() {
		return secondHint;
	}
	public void setSecondHint(DateTime secondHint) {
		this.secondHint = secondHint;
	}
	public DateTime getFinished() {
		return finished;
	}
	public void setFinished(DateTime finished) {
		this.finished = finished;
	}
	public TaskState getState() {
		return state;
	}
	public void setState(TaskState state) {
		this.state = state;
	}
	public TaskResult getResult() {
		return result;
	}
	public void setResult(TaskResult result) {
		this.result = result;
	}
	
	public void advanceState() {
		if (state == TaskState.OBTAINED) {
			firstHint = new DateTime();
			state = TaskState.FIRST_HINT;
		} else if (state == TaskState.FIRST_HINT) {
			secondHint = new DateTime();
			state = TaskState.SECOND_HINT;
		} else if (state == TaskState.SECOND_HINT) {
			finish(TaskResult.TIMEOUT);
		} else {
			throw new IllegalStateException("'FINISHED' state cannot be advanced.");
		}
	}
	
	public void setGuessed() {
		if (state == TaskState.OBTAINED) {
			finish(TaskResult.GUESSED);
		} else if (state == TaskState.FIRST_HINT) {
			finish(TaskResult.FIRST_HINT_GUESSED);
		} else if (state == TaskState.SECOND_HINT) {
			finish(TaskResult.SECOND_HINT_GUESSED);
		}
	}

	public void finish(TaskResult result) {
		this.result = result;
		state = TaskState.FINISHED;
		finished = new DateTime();
	}
	
	public boolean incrementAttempts() {
		return (++attempts == MAX_ATTEMPTS);
			
	}

	public int getAttempts() {
		return attempts;
	}
	
	public int getAttemptsLeft() {
		return MAX_ATTEMPTS - attempts;
	}
	
	public boolean isObtainedState() {
		return (state == TaskState.OBTAINED);
	}
	
	public boolean isFirstHintState() {
		return (state == TaskState.FIRST_HINT);
	}
	
	public boolean isSecondHintState() {
		return (state == TaskState.SECOND_HINT);
	}
	
	public boolean isFinishedState() {
		return (state == TaskState.FINISHED);
	}
	
	public boolean isGuessedResult() {
		return (result == TaskResult.GUESSED);
	}
	
	public boolean isFirstHintGuessedResult() {
		return (result == TaskResult.FIRST_HINT_GUESSED);
	}
	
	public boolean isSecondHintGuessedResult() {
		return (result == TaskResult.SECOND_HINT_GUESSED);
	}
	
	public boolean isRejectedResult() {
		return (result == TaskResult.REJECTED);
	}
	
	public boolean isTimeoutResult() {
		return (result == TaskResult.TIMEOUT);
	}
	
	public boolean isStopGameResult() {
		return (result == TaskResult.STOPPED);
	}
	
	public List<String> getAnswers() {
		return answers;
	}
	
	public void setAnswers(List<String> answers) {
		this.answers = answers;
	}
	
	public int getAnswersRemain() {
		return answers.size();
	}
	
	public int getAnswersTotal() {
		return task.getAnswers().size();
	}

	public void setGuessedCodes(int guessedCodes) {
		this.guessedCodes = guessedCodes;
	}

	public int getGuessedCodes() {
		return guessedCodes;
	}
}
